package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmNewsTaskService;
import com.heima.wemedia.thread.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private AutoScanService autoScanService;

    @Autowired
    private WmNewsTaskService wmNewsTaskService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private IArticleClient iArticleClient;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult submit(WmNewsDto dto) {
        // 1. 提取新闻内容
        WmNews news = getNews(dto);


        // 3. 判断是否为草稿
        Short status = dto.getStatus();
        if (status == 0) {
            log.info("文章为草稿，所以没有添加素材");
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        // 4. 提取内容图
        List<String> contentImages = getContentImages(dto.getContent());

        // 5. 提取封面图
        List<String> coverImages = new ArrayList<>();

        // 8. 自动布局
        if (dto.getType() == -1) {
            coverImages = autoLayout(contentImages);
            Integer coverImageSize = coverImages.size();
            if (coverImageSize == 3) {
                news.setType((short) 3);
                String images = StringUtils.join(coverImages.subList(0, 3), ",");
                news.setImages(images);
            } else if (coverImageSize < 3 && coverImageSize > 0) {
                news.setType((short) 1);
                news.setImages(coverImages.get(0));
            } else {
                news.setType((short) 0);
            }
        }
        // 2. 插入新闻表
        int newsResult = wmNewsMapper.insert(news);
        if (newsResult < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        // 6. 插入内容图
        addMaterial(contentImages, 1, news.getId());

        // 7. 插入封面图
        addMaterial(coverImages, 0, news.getId());

        //审核文章
            /*try {
               autoScanService.autoScanWmNews(wmNews.getId());
            } catch (Exception e) {
                throw new RuntimeException("文章审核失败");
         }*/
        try {
            wmNewsTaskService.addNewsToTask(news.getId(), news.getPublishTime());
        } catch (Exception e) {
            throw new RuntimeException("任务添加失败");
        }


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    public List<String> autoLayout(List<String> contentImages) {
        // 从内容图获取图片，填充到封面图上
        int size = contentImages.size();
        List<String> coverImages = new ArrayList<>();

        // 判断内容图的长度
        // 长度为 0 -> 无图
        if (size == 0) {
            return coverImages;
        }
        // 长度为 1 -> 单图
        else if (size == 1) {
            coverImages.add(contentImages.get(0));
            return coverImages;
        }
        // 长度大于3 -> 多图
        else if (size > 3) {
            coverImages.addAll(contentImages.subList(0, 3));
            return coverImages;
        }

        return contentImages;
    }


    public WmNews getNews(WmNewsDto dto) {
        if (dto == null) {
            log.warn("dto不能为空");
            return null;
        }

        WmNews wmNews = new WmNews();
        // 1. dto和wmNews相同字段进行赋值
        BeanUtils.copyProperties(dto, wmNews);

        // 2. 处理差异的字段
        if (dto.getType() == -1) {
            wmNews.setType(null);
        }

        List<String> images = dto.getImages();
        String imagesString = StringUtils.join(images, ",");
        wmNews.setImages(imagesString);
        wmNews.setCreatedTime(new Date());
        wmNews.setUserId(UserThreadLocal.get().getId());
        // 3. 返回wmNews

        return wmNews;
    }

    public List<String> getContentImages(String content) {
        // 1. 把content转成集合
        List<Map> maps = JSON.parseArray(content, Map.class);
        if (CollectionUtils.isEmpty(maps)) {
            log.warn("内容为空");
            return null;
        }

        List<String> imageList = new ArrayList<>();

        // 2. 遍历集合，找到里面type = image数据
        for (Map map : maps) {
            if (CollectionUtils.isEmpty(maps)) {
                continue;
            }

            Object type = map.get("type");
            if ("image".equals(type)) {
                try {
                    String value = (String) map.get("value");
                    imageList.add(value);
                } catch (Exception e) {
                    log.warn("value解析失败");
                    continue;
                }
            }
        }

        // 3. 提取value字段，形成一个List

        // 4. 把集合返回回去
        return imageList;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(List<String> images, Integer type, Integer newsId) {
        if (CollectionUtils.isEmpty(images)) {
            log.warn("素材不能为空");
            return false;
        }

        // 1. 遍历图片集合
        for (String image : images) {
            if (StringUtils.isEmpty(image)) {
                continue;
            }

            // 2. 判断当前图片是否存在于素材表中
            LambdaQueryWrapper<WmMaterial> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WmMaterial::getUrl, image);
            WmMaterial wmMaterial = wmMaterialMapper.selectOne(wrapper);

            Integer materialId = null;
            if (wmMaterial == null) {
                WmMaterial material = new WmMaterial();
                material.setUserId(UserThreadLocal.get().getId());
                material.setUrl(image);
                material.setIsCollection((short) 0);
                material.setType((short) 0);
                material.setCreatedTime(new Date());

                int materialResult = wmMaterialMapper.insert(material);
                if (materialResult < 1) {
                    log.warn("素材插入失败");
                    throw new RuntimeException("素材插入失败");
                }

                // 2.2 如不存在，插入素材，返回id
                materialId = material.getId();
            } else {
                // 2.1 如果已存在，返回id
                materialId = wmMaterial.getId();
            }

            // 3. 插入关系表
            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setMaterialId(materialId);
            newsMaterial.setNewsId(newsId);
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 0);

            int newMaterialResult = wmNewsMaterialMapper.insert(newsMaterial);
            if (newMaterialResult < 1) {
                throw new RuntimeException("素材关系插入失败");
            }
        }
        // 4. 返回true
        return true;
    }

    @Override
    public ResponseResult findList(WmNewsPageReqDto dto) {
        //开始时间
        Date beginPubDate = dto.getBeginPubDate();
        //频道id
        Integer channelId = dto.getChannelId();
        //结束时间
        Date endPubDate = dto.getEndPubDate();
        //关键字
        String keyword = dto.getKeyword();
        //当前页数
        Integer pageNum = dto.getPage();
        //一页几条
        Integer pageSize = dto.getSize();
        //状态
        Short status = dto.getStatus();

        //构造查询条件
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        //时间条件
        wrapper.between(beginPubDate != null && endPubDate != null, WmNews::getPublishTime, beginPubDate, endPubDate);
        //频道条件
        wrapper.eq(channelId != null, WmNews::getChannelId, channelId);
        //关键字条件
        wrapper.like(StringUtils.isNotEmpty(keyword), WmNews::getTitle, keyword);
        //状态条件
        wrapper.eq(status != null, WmNews::getStatus, status);

        //构造分页条件
        Page<WmNews> page = new Page<>(pageNum, pageSize);
        //分页查询
        Page<WmNews> wmNewsPage = wmNewsMapper.selectPage(page, wrapper);

        //组建结果返回
        Integer total = Math.toIntExact(wmNewsPage.getTotal());
        PageResponseResult result = new PageResponseResult(pageNum, pageSize, total);
        result.setData(wmNewsPage.getRecords());
        return result;
    }

    /**
     * 文章上架下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult upOrDown(WmNewsDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //根据dto传入过来的id找到对应的news
        Integer newsId = dto.getId();
        if (newsId == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNews news = wmNewsMapper.selectById(newsId);
        if (news == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断状态是否为已发布
        if (9 != news.getStatus()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //更新wm_news表中的enable字段
        if (news.getEnable() == 1) {
            news.setEnable((short) 0);
            int updateResult = wmNewsMapper.updateById(news);
            if (updateResult < 1) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "更新操作错误");
            }
        } else {
            news.setEnable((short) 1);
            int updateResult = wmNewsMapper.updateById(news);
            if (updateResult < 1) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "更新操作错误");
            }
        }

        //封装条件,将要修改的article_id发送给kafka
        Map<String, Object> map = new HashMap<>();
        map.put("articleId", news.getArticleId());
        map.put("enable", news.getEnable());

        kafkaTemplate.send("news.down.up.topic", JSON.toJSONString(map));


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);


    }

    /**
     * 查询需要人工审核的列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult newsList(NewsAuthDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取前端传入的参数
        Integer pageNum = dto.getPage();
        Integer pageSize = dto.getSize();
        dto.checkParam();
        dto.setPage((pageNum - 1) * pageSize);
        //查询要返回的数据
        List<WmNewsVo> list = wmNewsMapper.findDataList(dto);
        if (CollectionUtils.isEmpty(list)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "没有符合条件的文章");
        }
        //查询总数量
        Integer total = wmNewsMapper.findTotal(dto);
        PageResponseResult pageResponseResult = new PageResponseResult(pageNum, pageSize, total);
        pageResponseResult.setData(list);
        return pageResponseResult;
    }

    /**
     * news详情查询
     *
     * @param newsId
     * @return
     */
    @Override
    public ResponseResult newsText(Integer newsId) {
        if (newsId == null) {
            log.warn("newsId为空");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNewsVo newsVo = wmNewsMapper.findNewsText(newsId);
        if (newsVo == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "没查询到相关信息");
        }
        return ResponseResult.okResult(newsVo);
    }

    /**
     * 文章审核驳回
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult authFail(NewsAuthDto dto) {
        if (dto == null) {
            log.warn("前端传入dto为空");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Short status = dto.getStatus();
        WmNews wmNews = new WmNews();
        wmNews.setId(dto.getId());
        wmNews.setStatus(status);
        wmNews.setReason(dto.getMsg());
        int result = wmNewsMapper.updateById(wmNews);
        if (result <= 0) {
            log.warn("更新失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章审核通过
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult authPass(NewsAuthDto dto) {
        if (dto == null) {
            log.warn("前端传入dto为空");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //根据id去查新闻
        Integer newsId = dto.getId();
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WmNews::getId, newsId);
        WmNews wmNews = wmNewsMapper.selectOne(wrapper);
        //根据id去修改新闻状态
        WmNews wmNewsNew = new WmNews();
        wmNewsNew.setId(newsId);
        wmNewsNew.setReason(dto.getMsg());
        wmNewsNew.setStatus(dto.getStatus());
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult <= 0) {
            log.warn("更新通过状态失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //调用article保存文章
        ArticleDto articleDto = autoScanService.WmNews2ArticleDto(wmNews);
        if (articleDto == null) {
            throw new RuntimeException("news转article失败");
        }
        ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
        if (responseResult == null || responseResult.getCode() != 200) {
            throw new RuntimeException("保存文章失败");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);


    }
}
